package com.tcm.doctor.service;

import cn.hutool.core.util.NumberUtil;
import com.base.core.utils.ListUtils;
import com.base.core.utils.R;
import com.base.genid.generator.UidGenerator;
import com.tcm.core.service.ConfigService;
import com.tcm.doctor.domain.entity.Doctor;
import com.tcm.doctor.domain.enums.BusinessCodeEnum;
import com.tcm.doctor.domain.vo.ServicePriceVo;
import com.tcm.doctor.mapper.DoctorJobtitleMapper;
import com.tcm.doctor.mapper.DoctorMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@DubboService(version = "0.0.1-alpha", retries = 3, timeout = 6000, delay = -1)
public class PrescribePriceServiceImpl implements PrescribePriceService {

    @Autowired
    private DoctorMapper doctorMapper;

    @Autowired
    private DoctorJobtitleMapper doctorJobtitleMapper;

    @DubboReference(version = "0.0.1-alpha", retries = 3, timeout = 6000)
    private ConfigService configService;


    @DubboReference(version = "0.0.1-beta",group = "cached-uid",timeout = 6000, check = false,retries = 3)
    private UidGenerator uidGenerator;


    @Override
    public List<ServicePriceVo> servicePrice(Long doctorUserId) {
        //获取医生等级基础服务费
        Doctor doctor = doctorMapper.findByUserId(doctorUserId);
        Byte level = doctor.getJobtitleLevel();
        Integer basePrice = null;
        switch (level.intValue()){
            case 1:
                basePrice = new Integer(configService.findValue("first_base", "4"));
                break;
            case 2:
                basePrice = new Integer(configService.findValue("second_base", "5"));
                break;
            case 3:
                basePrice = new Integer(configService.findValue("second_base", "6"));
                break;
            default:
                R.throwFail(BusinessCodeEnum.ILLEGAL_LEVEL_VALUE.getCode(),
                        BusinessCodeEnum.ILLEGAL_LEVEL_VALUE.getMessage());
        }
        Integer serviceFeeLimit = new Integer(configService.findValue("service_fee_cap", "100"));
        return calculateServicePrice(basePrice, serviceFeeLimit);
    }

    /**
     * 计算服务费公式
     * @param baseServiceFee 基础服务费
     * @param serviceFeeLimit 服务费上限
     * @return
     */
    protected List<ServicePriceVo> calculateServicePrice(int baseServiceFee, int serviceFeeLimit){
        int feeSeries = 1;//药费等差数列首项
        int tolerance = 10;//药费公差数
        baseServiceFee = (baseServiceFee == 0) ? 4 : baseServiceFee;
        int toleranceServiceFee = baseServiceFee;
        serviceFeeLimit = (serviceFeeLimit == 0) ? 100 : serviceFeeLimit;
        List<ServicePriceVo> serviceFee = new ArrayList<>();
        do {
            ServicePriceVo servicePriceVo = new ServicePriceVo();
            servicePriceVo.setFeeSeries(feeSeries);
            servicePriceVo.setServicePrice(baseServiceFee);
            servicePriceVo.setTitle("￥"+ NumberUtil.decimalFormatMoney(baseServiceFee)+"元");
            servicePriceVo.setTolerance(tolerance);
            serviceFee.add(servicePriceVo);
            baseServiceFee = baseServiceFee + toleranceServiceFee;
            feeSeries = feeSeries + tolerance;
        }while (baseServiceFee <= serviceFeeLimit);
        return serviceFee;
    }

    /**
     * 根据药价获得服务费
     * @param drugsPrice
     * @return
     */
    @Override
    public int defaultServicePrice(BigDecimal drugsPrice, Long doctorUserId){
        int drugsFee = NumberUtil.round(drugsPrice, 0).intValue();
        int serviceFee = 0;
        int serviceFeeLimit = new Integer(configService.findValue("service_fee_cap", "100"));
        List<ServicePriceVo> servicePriceVos = servicePrice(doctorUserId);
        if(ListUtils.isNotEmpty(servicePriceVos)) {
            for (ServicePriceVo servicePriceVo : servicePriceVos) {
                if ((drugsFee >= servicePriceVo.getFeeSeries()) &&
                        (drugsFee < (NumberUtil.add(servicePriceVo.getFeeSeries() , servicePriceVo.getTolerance())))) {
                    serviceFee = servicePriceVo.getServicePrice();
                    break;
                }else if(drugsFee >= (NumberUtil.add(servicePriceVo.getFeeSeries() , servicePriceVo.getTolerance()))){
                    serviceFee = serviceFeeLimit;
                }
            }
            if (serviceFee == 0){
                serviceFee = servicePriceVos.get(0).getServicePrice();
            }
        }
        return serviceFee;
    }
}
